package com.terra.ns.imp.system.service.impl

import com.terra.ns.imp.common.vo.request.ByCodeRequest
import com.terra.ns.imp.common.vo.request.PageParam
import com.terra.ns.imp.common.vo.request.QueryByKeywordsRequest
import com.terra.ns.imp.common.vo.response.PageResult
import com.terra.ns.imp.system.constant.SystemErrorCode
import com.terra.ns.imp.system.convert.RoleConvert
import com.terra.ns.imp.system.convert.UserRoleRelConvert
import com.terra.ns.imp.system.entity.StRole
import com.terra.ns.imp.system.exception.SystemServiceException
import com.terra.ns.imp.system.mapper.StRoleMapper
import com.terra.ns.imp.system.mapper.StUserRoleRelMapper
import com.terra.ns.imp.system.service.IStRoleService
import com.terra.ns.imp.system.vo.base.RoleBaseRequest
import com.terra.ns.imp.system.vo.base.RoleBaseResponse
import com.terra.ns.imp.system.vo.request.EditRoleRequest
import com.terra.ns.imp.system.vo.request.RoleAssignPermRequest
import com.terra.ns.imp.system.vo.request.RoleAssignUserRequest
import com.terra.ns.imp.system.vo.response.RolePermResponse
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

/**
@author qins
@date 2023/6/6
@desc
 */
@Service
class StRoleServiceImpl: IStRoleService {

    @Autowired
    private lateinit var roleMapper: StRoleMapper

    @Autowired
    private lateinit var userRoleRelMapper: StUserRoleRelMapper


    @Transactional
    override fun addRole(request: RoleBaseRequest) {
        checkRole(null, request.name)
        val insertRole = RoleConvert.convert(request)
        roleMapper.insert(insertRole)
    }

    @Transactional
    override fun updateRole(request: EditRoleRequest) {
        checkRole(request.code, request.name)
        val updateRole = RoleConvert.convert(request)
        roleMapper.updateRoleAllFieldByCode(updateRole, request.code, listOf(StRole::code.name,  StRole::status.name))
    }

    @Transactional
    override fun deleteRole(request: ByCodeRequest) {
        checkRoleExist(request.code)
        //删除角色
        roleMapper.deleteByCode(request.code)
        //删除关联数据
        userRoleRelMapper.deleteByRoleCode(request.code)
    }

    @Transactional
    override fun assignUser(request: RoleAssignUserRequest) {
        checkRoleExist(request.code)
        associateUser(request.code, request.userCodeList)
    }

    override fun selectRoleList(request: QueryByKeywordsRequest): List<RoleBaseResponse> {
        val roleList = roleMapper.selectLikeName(request.keywords)
        return roleList.map { RoleConvert.convertToBaseResponse(it) }
    }

    override fun selectRolePage(request: PageParam<QueryByKeywordsRequest>): PageResult<RoleBaseResponse> {
        TODO("Not yet implemented")
    }

    override fun selectRoleDetail(request: ByCodeRequest): RoleBaseResponse {
        val role = roleMapper.selectOneByCode(request.code)
            ?: throw SystemServiceException(SystemErrorCode.ROLE_NOT_EXIST)
        return RoleConvert.convertToBaseResponse(role)
    }

    override fun assignPerm(request: RoleAssignPermRequest) {
        TODO("Not yet implemented")
    }

    override fun selectRolePerm(request: ByCodeRequest): RolePermResponse {
        TODO("Not yet implemented")
//        val role = roleMapper.selectOneByCode(request.code, LoginUtils.getTenantId())
//            ?: throw SystemServiceException(SystemErrorCode.ROLE_NOT_EXIST)
//        val permRoleList = permRoleRelMapper.selectByRoleCodeList(listOf(request.code))
//        if (permRoleList.isEmpty()) return null
//        val permList = permMapper.selectByCodeList(permRoleList.mapNotNull { it.permissionCode }, request.type)
//        val permResponseList = permList.map { TePermConvertor.convertToBaseResponse(it) }
//        return RoleConvert.convertToRolePermResponse(role, permResponseList)
    }

    private fun checkRole(code: String?, name: String?) {
        checkRoleExist(code)
        checkNameUnique(code, name)
    }

    /**
     * 查询角色编码是否存在
     */
    private fun checkRoleExist(code: String?) {
        if (code == null) return
        roleMapper.selectOneByCode(code) ?: throw SystemServiceException(SystemErrorCode.ROLE_NOT_EXIST)
    }

    /**
     * 查询角色名称唯一性
     */
    private fun checkNameUnique(code: String?, name: String?) {
        if (name.isNullOrBlank()) throw SystemServiceException(SystemErrorCode.ROLE_NAME_ERROR)
        val role = roleMapper.selectOneByName(name) ?: return
        if (code == null || code != role.code) {
            throw SystemServiceException(SystemErrorCode.ROLE_NAME_EXIST)
        }
    }

    /**
     * 给角色关联用户
     */
    private fun associateUser(code: String, userCodeList: List<String>?) {
        // 对比以前关联的用户
        val existUserCodeList = userRoleRelMapper.selectListByRoleCodeAndTenantId(code).mapNotNull { it.userCode }
        // 交集  不做变更的数据
        val intersect = existUserCodeList.intersect((userCodeList ?: emptyList()).toSet())
        // 以前的去除交集(与之做差集)--需要删除的
        val delList = existUserCodeList.subtract(intersect)
        // 现在的去除交集(与之做差集)--需要新增的
        val insertList = (userCodeList ?: emptyList()).subtract(intersect)
        if (delList.isNotEmpty()) {
            userRoleRelMapper.deleteByUserCodesAndRoleCodes(delList.toList(), listOf(code))
        }
        if (insertList.isNotEmpty()) {
            userRoleRelMapper.batchInsertByBatchSize(insertList.map { UserRoleRelConvert.convert(it, code) })
        }
    }

}